package reflecttest

import (
	"fmt"
	"reflect"
)

func Execute() {
	TestReflect()
}

type User struct {
	Id    int
	Age   int
	Name  string
	Class string
}

func (user User) _privateM() {

}

func (user User) ShowInfo() {
	fmt.Printf("Hi All, I am %s. I am %d years old. Thank you.\n", user.Name, user.Age)
}

func (user User) SayHi(name string) {
	fmt.Printf("Hello, %s !\n", name)
}

func TestReflect() {
	u := User{Id: 1, Age: 12, Name: "Erin", Class: "FastTwo"}
	v := reflect.ValueOf(&u)

	// 通过方法名返回方法
	m1 := v.MethodByName("ShowInfo")

	if m1.IsValid() { // 检查该方法是否能被访问
		p1 := []reflect.Value{}
		m1.Call(p1)
	} else {
		fmt.Println("Method ShowInfo is not found or not exported.")
	}

	// 放方法需要传入一个参数时
	m2 := v.MethodByName("SayHi")
	if m2.IsValid() {
		p2 := []reflect.Value{
			reflect.ValueOf("World"),
		}
		m2.Call(p2)
	} else {
		fmt.Println("Method SayHi is not found or not exported.")
	}

	// 私有方法，IsValid会返回true
	m3 := v.MethodByName("_privateM")
	if m3.IsValid() {
		p3 := []reflect.Value{}
		m3.Call(p3)
	} else {
		fmt.Println("Method _privateM is not found or not exported.")
	}

	// 获取所有方法
	mnums := v.NumMethod()
	fmt.Println(mnums)
	for i := 0; i < mnums; i++ {
		m := v.Method(i)
		fmt.Println(m.String())
		paramsNum := m.Type().NumIn() // 查看方法参数个数
		fmt.Printf("paramsNum: %v\n", paramsNum)
		for i := 0; i < paramsNum; i++ {
			param := m.Type().In(i) // 查看方法参数类型
			fmt.Printf("param: %v\n", param)
		}
	}
}
